#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "set.h"
#include "set_errno.h"

#define SENTINEL '\0'

struct set set__empty(void)
{
  struct set tmp;
  
  tmp.s[0] = SENTINEL;
  
  return tmp;
}

int set__is_empty(const struct set * set) {
  assert(set != NULL);
  return (set->s[0] == SENTINEL);
}

size_t set__size(const struct set* set)
{
  assert(set != NULL);
  size_t i;
  
  for (i = 0; set->s[i] != SENTINEL; i++)
    ;
  
  return i;
  /*
  const char * p = set->s;

  // Counts elements up to SENTINEL
  while (*p != SENTINEL)
    ++p;

  return (p - set->s);
  */
}

int set__find(const struct set* set, char c)
{
  assert(set != NULL);
  int i;
  
  for (i = 0; set->s[i] != SENTINEL; i++)
    if(set->s[i] == c)
      return 1;
  
  return 0;
}

int set__add(struct set* set, char c)
{
  assert(set != NULL);

  int size = set__size(set);
  
  if(set__find(set, c))
    {
      set__errno = SET__ELEMENT_DUPLICATION;
      return 1;
    }
  
  if(size + 1 >= SET__SIZE)
    {
      set__errno = SET__CAPACITY_EXCEEDED;
      return 1;
    }
  
  set->s[size] = c;
  set->s[size + 1] = SENTINEL;
  
  return 0;
}

int set__remove(struct set * set, char f) {
  assert(set != NULL);

  char * p = set->s, * q = NULL;

  // Searches f and SENTINEL in s
  for (p = set->s; *p != SENTINEL; ++p)
    if (*p == f)
      q = p;

  // Error when f is not in s
  if (NULL == q) {
    set__errno = SET__ELEMENT_UNKNOWN;
    return -1;
  }

  // Put the last element in place of f
  *q = *(p - 1);
  *(p - 1) = SENTINEL;

  return 0;
}


int set__inter(const struct set * s1, const struct set * s2, struct set * si)
{
  assert(s1 != NULL);
  assert(s2 != NULL);
  assert(set__is_empty(si));

  char err = 0;
  const char * p;
  
  // Add to si all elements of s1 that belong to s2
  for (p = s1->s; *p != SENTINEL; ++p)
    if (set__find(s2, *p))
      err |= set__add(si, *p) == 0;

  return !err;
}

int set__union(const struct set * s1, const struct set * s2, struct set * su)
{
  assert(s1 != NULL);
  assert(s2 != NULL);
  assert(set__is_empty(su));

  char err = 0;
  const char * p;

  // Add all elements of s1 and all elements of s2 to su
  for (p = s1->s; *p != SENTINEL; ++p)
    err |= set__add(su, *p) == 0;
  
  for (p = s2->s; *p != SENTINEL; ++p)
    err |= set__add(su, *p) == 0;
  
  return !err;
}

